home *** CD-ROM | disk | FTP | other *** search
/ Greenhouse Effect Detection Expriment / NASA Greenhouse Effect Detection Expriment 1992 - Disc 2.iso / software / dos / cdf22pc / src / lib / dirutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-02  |  20.5 KB  |  875 lines

  1. /******************************************************************************
  2. *
  3. *  NSSDC/CDF                            Directory utilities.
  4. *
  5. *  Version 1.0, 3-Mar-92, ST Systems (STX)
  6. *
  7. *  Modification history:
  8. *
  9. *   V1.0   3-Mar-92, J Love    Original version.
  10. *
  11. *****************************************************************************/
  12.  
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17.  
  18. #if defined(__MSDOS__)        /* Borland/Turbo C */
  19. #include <dir.h>
  20. #include <dos.h>
  21. #include <sys\stat.h>
  22. #endif
  23.  
  24. #if defined(MSDOS)        /* Microsoft C */
  25. #include <dos.h>
  26. #include <sys\types.h>
  27. #include <sys\stat.h>
  28. #endif
  29.  
  30. #if defined(unix)
  31. #include <dirent.h>
  32. #include <pwd.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #endif
  36.  
  37. #if defined(vms)
  38. #include <rmsdef.h>
  39. #include <descrip.h>
  40. #include <stat.h>
  41. #include <lib$routines.h>
  42. #endif
  43.  
  44. #include "dirutils.h"
  45.  
  46. #if defined(unix)
  47. static int PatternMatch ();
  48. static int CheckPattern ();
  49. static void DerefEnvVar ();
  50. static char *NextNonENVchar ();
  51. enum typeENUM {TBD, STR, WILD1, WILDn};
  52. #endif
  53.  
  54. /******************************************************************************
  55. * DirList.
  56. ******************************************************************************/
  57.  
  58. int DirList (path, dirS, nameS)
  59. char *path;
  60. char ***dirS;
  61. char ***nameS;
  62. {
  63. int i;
  64. int nFiles = 0;
  65. int tNameChars = 0;
  66. int tDirChars = 0;
  67. char dir[MAX_PATH_LEN + 1];
  68. char pattern[MAX_NAME_LEN + 1];
  69.  
  70. struct FILEstruct {
  71. char *name;
  72. char *dir;
  73. struct FILEstruct *next;
  74. };
  75.  
  76. struct FILEstruct *FILEhead = NULL;
  77. struct FILEstruct *FILEtail = NULL;
  78. struct FILEstruct *FILEptr;
  79. struct FILEstruct *FILEptrT;
  80. char *dirP, *nameP;
  81.  
  82. #if defined(__MSDOS__)
  83. char pathX[MAX_PATH_LEN + 1];
  84. struct ffblk ffblk;
  85. int done;
  86. #endif
  87.  
  88. #if defined(MSDOS)
  89. char pathX[MAX_PATH_LEN + 1];
  90. struct find_t fileinfo;
  91. int done;
  92. #endif
  93.  
  94. #if defined(unix)
  95. DIR *dirp;
  96. struct dirent *dp;
  97. char dirX[MAX_PATH_LEN + 1];
  98. #endif
  99.  
  100. #if defined(vms)
  101. #if 0
  102. char curDir[MAX_DIR_LEN + 1];
  103. #endif
  104.  
  105. #if 1
  106. char ignoredDir[MAX_DIR_LEN + 1];
  107. #endif
  108.  
  109. char pathX[MAX_PATH_LEN + 1];
  110. static char pathFound[MAX_PATH_LEN + 1];
  111. static $DESCRIPTOR (pathDESCR, "");
  112. static $DESCRIPTOR (pathFoundDESCR, pathFound);
  113. unsigned long context = 0;
  114. char name[MAX_NAME_LEN + 1];
  115. unsigned long int status;
  116. #endif
  117.  
  118. /******************************************************************************
  119. * Find files on MS-DOS machine.  Note that only one directory is possible
  120. * on MS-DOS systems.
  121. ******************************************************************************/
  122.  
  123. #if defined(__MSDOS__) | defined(MSDOS)
  124. ParsePath (path, dir, pattern);
  125.  
  126. #if 0
  127. if (dir[0] == NUL) strcpy (dir, ".");    /* Default to current directory. */
  128. #endif
  129.  
  130. ExpandPath (path, pathX);
  131.  
  132. #if defined(__MSDOS__)
  133. done = findfirst (pathX, &ffblk, 0);
  134. #endif
  135.  
  136. #if defined(MSDOS)
  137. done = _dos_findfirst (pathX, 0, &fileinfo);
  138. #endif
  139.  
  140. while ( ! done) {
  141.   /****************************************************************************
  142.   * Allocate/setup file structure.
  143.   ****************************************************************************/
  144.  
  145.   FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
  146.  
  147. #if defined(__MSDOS__)
  148.   FILEptr->name = (char *) malloc (strlen(ffblk.ff_name) + 1);
  149.   strcpy (FILEptr->name, ffblk.ff_name);
  150.   tNameChars += strlen(ffblk.ff_name) + 1;
  151. #endif
  152.  
  153. #if defined(MSDOS)
  154.   FILEptr->name = (char *) malloc (strlen(fileinfo.name) + 1);
  155.   strcpy (FILEptr->name, fileinfo.name);
  156.   tNameChars += strlen(fileinfo.name) + 1;
  157. #endif
  158.  
  159.   nFiles++;
  160.  
  161.   if (FILEhead == NULL) {
  162.     FILEptr->dir = (char *) malloc (strlen(dir) + 1);
  163.     strcpy (FILEptr->dir, dir);
  164.     tDirChars += strlen(dir) + 1;
  165.   }
  166.   else
  167.     FILEptr->dir = NULL;
  168.  
  169.   FILEptr->next = NULL;
  170.  
  171.   /****************************************************************************
  172.   * Add to linkedlist.
  173.   ****************************************************************************/
  174.  
  175.   if (FILEhead == NULL)
  176.     FILEhead = FILEptr;
  177.   else
  178.     FILEtail->next = FILEptr;
  179.  
  180.   FILEtail = FILEptr;
  181.  
  182.   /****************************************************************************
  183.   * Get next matching file.
  184.   ****************************************************************************/
  185.  
  186. #if defined(__MSDOS__)
  187.   done = findnext (&ffblk);
  188. #endif
  189.  
  190. #if defined(MSDOS)
  191.   done = _dos_findnext (&fileinfo);
  192. #endif
  193. }
  194. #endif
  195.  
  196. /******************************************************************************
  197. * Find files on UNIX machine.  Note that only one directory is possible on
  198. * UNIX systems.
  199. ******************************************************************************/
  200.  
  201. #if defined(unix)
  202. ParsePath (path, dir, pattern);
  203.  
  204. #if 0
  205. if (dir[0] == NUL) strcpy (dir, ".");        /* Default to current dir. */
  206. #endif
  207.  
  208. if (pattern[0] == NUL) strcpy (pattern, "*");    /* Default to all files. */
  209.  
  210. ExpandPath (dir, dirX);
  211.  
  212. #if 1
  213. if (dirX[0] == NUL) strcpy (dirX, ".");        /* Default to current dir. */
  214. #endif
  215.  
  216. dirp = opendir (dirX);
  217. if (dirp == NULL) return -1;
  218.  
  219. dp = readdir (dirp);
  220.  
  221. while (dp != NULL) {
  222.   if (PatternMatch (pattern, dp->d_name)) {
  223.     /**************************************************************************
  224.     * Allocate/setup file structure.
  225.     **************************************************************************/
  226.  
  227.     FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
  228.  
  229.     FILEptr->name = (char *) malloc (strlen(dp->d_name) + 1);
  230.     strcpy (FILEptr->name, dp->d_name);
  231.     tNameChars += strlen(dp->d_name) + 1;
  232.     nFiles++;
  233.  
  234.     if (FILEhead == NULL) {
  235.       FILEptr->dir = (char *) malloc (strlen(dir) + 1);
  236.       strcpy (FILEptr->dir, dir);
  237.       tDirChars += strlen(dir) + 1;
  238.     }
  239.     else
  240.       FILEptr->dir = NULL;
  241.  
  242.     FILEptr->next = NULL;
  243.  
  244.     /**************************************************************************
  245.     * Add to linked list.
  246.     **************************************************************************/
  247.  
  248.     if (FILEhead == NULL)
  249.       FILEhead = FILEptr;
  250.     else
  251.       FILEtail->next = FILEptr;
  252.  
  253.     FILEtail = FILEptr;
  254.   }
  255.  
  256.   /****************************************************************************
  257.   * Get next file.
  258.   ****************************************************************************/
  259.  
  260.   dp = readdir (dirp);
  261. }
  262.  
  263. closedir (dirp);
  264. #endif
  265.  
  266. /******************************************************************************
  267. * Find files on VMS machine.
  268. ******************************************************************************/
  269.  
  270. #if defined(vms)
  271. ParsePath (path, dir, pattern);
  272. ExpandPath (path, pathX);
  273.  
  274. pathDESCR.dsc$a_pointer = pathX;
  275. pathDESCR.dsc$w_length = strlen(pathX);
  276.  
  277. while ((status = lib$find_file (&pathDESCR, &pathFoundDESCR, &context,
  278.                 NULL, NULL, NULL, NULL)) == RMS$_NORMAL) {
  279.   /****************************************************************************
  280.   * A file was found, NUL terminate and remove trailing blanks.
  281.   ****************************************************************************/
  282.  
  283.   pathFound[pathFoundDESCR.dsc$w_length] = NUL;           /* NUL-terminate. */
  284.  
  285.   for (i = strlen(pathFound) - 1;
  286.        i >= 0 && pathFound[i] == ' '; i--) pathFound[i] = NUL;
  287.  
  288. #if 0    /* SHOULD VERSION BE STRIPPED OFF? */
  289.   if ((cp = strrchr (pathFound, ';')) != NULL) *cp = NUL;  /* Strip version. */
  290. #endif
  291.  
  292.   ParsePath (pathFound, ignoredDir, name);
  293.  
  294.   /****************************************************************************
  295.   * Allocate/setup file structure.
  296.   ****************************************************************************/
  297.  
  298.   FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
  299.  
  300.   FILEptr->name = (char *) malloc (strlen(name) + 1);
  301.   strcpy (FILEptr->name, name);
  302.   tNameChars += strlen(name) + 1;
  303.   nFiles++;
  304.  
  305.   if (FILEhead == NULL) {
  306.     FILEptr->dir = (char *) malloc (strlen(dir) + 1);
  307.     strcpy (FILEptr->dir, dir);
  308.     tDirChars += strlen(dir) + 1;
  309.  
  310. #if 0
  311.     strcpy (curDir, dir);
  312. #endif
  313.   }
  314.  
  315. #if 0
  316.   else
  317.     if (strcmp(dir,curDir) != 0) {
  318.       FILEptr->dir = (char *) malloc (strlen(dir) + 1);
  319.       strcpy (FILEptr->dir, dir);
  320.       tDirChars += strlen(dir) + 1;
  321.       strcpy (curDir, dir);
  322.     }
  323. #endif
  324.  
  325.     else
  326.       FILEptr->dir = NULL;
  327.  
  328.   FILEptr->next = NULL;
  329.  
  330.   /****************************************************************************
  331.   * Add to linked list.
  332.   ****************************************************************************/
  333.  
  334.   if (FILEhead == NULL)
  335.     FILEhead = FILEptr;
  336.   else
  337.     FILEtail->next = FILEptr;
  338.  
  339.   FILEtail = FILEptr;
  340. }
  341.  
  342. status = lib$find_file_end (&context);
  343. #endif
  344.  
  345. /******************************************************************************
  346. * Build directory/file arrays.
  347. ******************************************************************************/
  348.  
  349. if (nFiles > 0) {
  350.   /****************************************************************************
  351.   * Setup to traverse linked list.
  352.   ****************************************************************************/
  353.  
  354.   *dirS = (char **) malloc ((nFiles*sizeof(char *)) + tDirChars);
  355.   *nameS = (char **) malloc ((nFiles*sizeof(char *)) + tNameChars);
  356.  
  357.   dirP = (char *) (*dirS) + nFiles*sizeof(char *);
  358.   nameP = (char *) (*nameS) + nFiles*sizeof(char *);
  359.   FILEptr = FILEhead;
  360.  
  361.   /****************************************************************************
  362.   * Traverse linked list of file structures.
  363.   ****************************************************************************/
  364.  
  365.   for (i = 0; i < nFiles; i++) {
  366.      if (FILEptr->dir != NULL) {
  367.        strcpy (dirP, FILEptr->dir);
  368.        (*dirS)[i] = dirP;
  369.        dirP += strlen(FILEptr->dir) + 1;
  370.      }
  371.      else
  372.        (*dirS)[i] = (*dirS)[i-1];    /* Same as the last one.  A directory
  373.                        must exist for the first file. */
  374.      strcpy (nameP, FILEptr->name);
  375.      (*nameS)[i] = nameP;
  376.      nameP += strlen(FILEptr->name) + 1;
  377.  
  378.      FILEptr = FILEptr->next;
  379.   }
  380.  
  381.   /****************************************************************************
  382.   * Free linked list of file structures.
  383.   ****************************************************************************/
  384.  
  385.   FILEptr = FILEhead;
  386.  
  387.   while (FILEptr != NULL) {
  388.     FILEptrT = FILEptr;
  389.     FILEptr = FILEptr->next;
  390.     if (FILEptrT->dir != NULL) free (FILEptrT->dir);
  391.     free (FILEptrT->name);
  392.     free (FILEptrT);
  393.   }
  394. }
  395. else {
  396.   /****************************************************************************
  397.   * No files found.
  398.   ****************************************************************************/
  399.  
  400.   *nameS = NULL;
  401.   *dirS = NULL;
  402. }
  403.  
  404. return nFiles;                /* Return number of files found. */
  405. }
  406.  
  407. /******************************************************************************
  408. * ParsePath.
  409. ******************************************************************************/
  410.  
  411. void ParsePath (path, dir, pattern)
  412. char *path;
  413. char *dir;
  414. char *pattern;
  415. {
  416. char *cp;
  417. int len;
  418.  
  419. #if defined(unix)
  420. if (IsDir(path)) {
  421.   strcpy (dir, path);
  422.   pattern[0] = NUL;
  423. }
  424. else {
  425.   cp = strrchr (path, '/');
  426.   if (cp == NULL) {
  427.     dir[0] = NUL;
  428.     strcpy (pattern, path);
  429.   }
  430.   else {
  431.     len = cp - path;        /* '/' not returned as part of directory. */
  432.     strncpy (dir, path, len);
  433.     dir[len] = NUL;
  434.     strcpy (pattern, cp + 1);
  435.   }
  436. }
  437. #endif
  438.  
  439. #if defined(__MSDOS__) | defined(MSDOS)
  440. if (IsDir(path)) {
  441.   strcpy (dir, path);
  442.   pattern[0] = NUL;
  443. }
  444. else {
  445.   char *cp1 = strrchr (path, ':');
  446.   char *cp2 = strrchr (path, '\\');
  447.  
  448.   cp = (cp1 > cp2 ? cp1 : cp2);
  449.  
  450.   if (cp == NULL) {
  451.     dir[0] = NUL;
  452.     strcpy (pattern, path);
  453.   }
  454.   else {
  455.     if (cp1 == NULL) {
  456.       len = cp2 - path;        /* '\' not returned as part of directory. */
  457.       strncpy (dir, path, len);
  458.       dir[len] = NUL;
  459.     }
  460.     else {
  461.       if (cp2 == NULL) {
  462.     len = cp1 - path + 1;    /* ':' is returned as part of directory. */
  463.     strncpy (dir, path, len);
  464.     dir[len] = NUL;
  465.       }
  466.       else {
  467.     if (cp1 + 1 == cp2)
  468.       len = cp2 - path + 1;    /* ':' is returned as part of directory. */
  469.     else
  470.       len = cp2 - path;    /* ':' not returned as part of directory. */
  471.     strncpy (dir, path, len);
  472.     dir[len] = NUL;
  473.       }
  474.     }
  475.     strcpy (pattern, cp + 1);
  476.   }
  477. }
  478. #endif
  479.  
  480. #if defined(vms)
  481. char *cp1 = strrchr (path, ':');
  482. char *cp2 = strrchr (path, ']');
  483.  
  484. cp = (cp1 > cp2 ? cp1 : cp2);
  485.  
  486. if (cp == NULL) {
  487.   dir[0] = NUL;
  488.   strcpy (pattern, path);
  489. }
  490. else {
  491.   len = cp - path + 1;        /* ':' or ']' returned as part of directory. */
  492.   strncpy (dir, path, len);
  493.   dir[len] = NUL;
  494.   strcpy (pattern, cp + 1);
  495. }
  496. #endif
  497.  
  498. return;
  499. }
  500.  
  501. /******************************************************************************
  502. * ExpandPath.
  503. ******************************************************************************/
  504.  
  505. void ExpandPath (shortP, longP)
  506. char *shortP;
  507. char *longP;
  508. {
  509. #if defined(unix)
  510. int len;
  511. char username[MAX_USERNAME_LEN+1];
  512. char tempP[MAX_PATH_LEN+1];
  513. char *tail;
  514. struct passwd *pw;
  515. #endif
  516.  
  517. #if defined(unix)
  518. DerefEnvVar (shortP, tempP);
  519.  
  520. if (tempP[0] != '~')
  521.   strcpy (longP, tempP);
  522. else {
  523.   tail = strchr (tempP, '/');
  524.  
  525.   if (tail != NULL) {
  526.     len = tail - (tempP + 1);
  527.  
  528.     if (len > 0) {
  529.       strncpy (username, tempP + 1, len);
  530.       username[len] = NUL;
  531.       pw = getpwnam (username);
  532.     }
  533.     else
  534.       pw = getpwuid (getuid());
  535.  
  536.     if (pw != NULL)
  537.       strcpy (longP, pw->pw_dir);
  538.     else
  539.       strcpy (longP, "?");
  540.  
  541.     strcat (longP, tail);
  542.   }
  543.   else {
  544.     if (tempP[1] != NUL)
  545.       pw = getpwnam (tempP + 1);
  546.     else
  547.       pw = getpwuid (getuid());
  548.  
  549.     if (pw != NULL)
  550.       strcpy (longP, pw->pw_dir);
  551.     else
  552.       strcpy (longP, "?");
  553.   }
  554. }
  555. #endif
  556.  
  557. #if defined(__MSDOS__) | defined(MSDOS)
  558. strcpy (longP, shortP);
  559. #endif
  560.  
  561. #if defined(vms)
  562. strcpy (longP, shortP);
  563. #endif
  564.  
  565. return;
  566. }
  567.  
  568. /******************************************************************************
  569. * IsDir (directory).
  570. ******************************************************************************/
  571.  
  572. int IsDir (path)
  573. char *path;
  574. {
  575. char pathX[MAX_PATH_LEN+1];
  576. struct stat st;
  577.  
  578. ExpandPath (path, pathX);
  579.  
  580. #if defined(unix) | defined(__MSDOS__) | defined(MSDOS)
  581. if (stat(pathX, &st) == 0)
  582.   return ((st.st_mode & S_IFDIR) ? TRUE : FALSE);
  583. else
  584.   return FALSE;
  585. #endif
  586.  
  587. #if defined(vms)
  588. if (IsReg(pathX))        /* First check for possible logical name
  589.                    defined to be a full file specification
  590.                    (not just a directory). */
  591.   return FALSE;
  592. else {                /* If not, check if the path ends with a ':'
  593.                    (logical name) or ']' (directory). */
  594.   int x = strlen(pathX) - 1;
  595.   if (pathX[x] == ':' || pathX[x] == ']')
  596.     return TRUE;
  597.   else
  598.     return FALSE;
  599. }
  600. #endif
  601.  
  602. }
  603.  
  604. /******************************************************************************
  605. * IsReg (regular file).  'stat' on VMS and MS-DOS systems will indicate a
  606. *             regular file if ANY file can be found matching a
  607. *             wildcard spec.  On UNIX systems, that doesn't happen.
  608. ******************************************************************************/
  609.  
  610. int IsReg (path)
  611. char *path;
  612. {
  613. char pathX[MAX_PATH_LEN+1];
  614. struct stat st;
  615.  
  616. ExpandPath (path, pathX);
  617.  
  618. #if defined(vms)
  619. if (strchr(pathX,'*') != NULL || strchr(pathX,'%') != NULL) return FALSE;
  620. #endif
  621.  
  622. #if defined(__MSDOS__) | defined(MSDOS)
  623. if (strchr(pathX,'*') != NULL || strchr(pathX,'?') != NULL) return FALSE;
  624. #endif
  625.  
  626. if (stat(pathX, &st) == 0)
  627.   return ((st.st_mode & S_IFREG) ? TRUE : FALSE);
  628. else
  629.   return FALSE;
  630. }
  631.  
  632. /******************************************************************************
  633. * PatternMatch. (Only used on UNIX systems).
  634. ******************************************************************************/
  635.  
  636. #if defined(unix)
  637. static int PatternMatch (pattern, name)
  638. char *pattern;
  639. char *name;
  640. {
  641. enum typeENUM types[MAX_PATTERNS];
  642. char *strings[MAX_PATTERNS];
  643. int nTypes = 0;
  644. int len, i, result;
  645.  
  646. for (i = 0; i < MAX_PATTERNS; i++) types[i] = TBD;
  647.  
  648. for (i = 0; pattern[i] != NUL; i++)
  649.    switch (pattern[i]) {
  650.      case '?':
  651.        types[nTypes++] = WILD1;
  652.        break;
  653.      case '*':
  654.        if (nTypes == 0 || types[nTypes] != WILDn) types[nTypes++] = WILDn;
  655.        break;
  656.      default:
  657.        if (types[nTypes] == TBD) {
  658.      types[nTypes] = STR;
  659.      strings[nTypes] = (char *) malloc (MAX_NAME_LEN + 1);
  660.      strings[nTypes][0] = pattern[i];
  661.      strings[nTypes][1] = NUL;
  662.      nTypes++;
  663.        }
  664.        else {
  665.      len = strlen (strings[nTypes-1]);
  666.      strings[nTypes-1][len] = pattern[i];
  667.      strings[nTypes-1][len+1] = NUL;
  668.        }
  669.    }
  670.  
  671. result = CheckPattern (nTypes, types, strings, name);
  672.  
  673. for (i = 0; i < MAX_PATTERNS; i++) {
  674.    if (types[i] == STR) free (strings[i]);
  675. }
  676.  
  677. return result;
  678. }
  679. #endif
  680.  
  681. /******************************************************************************
  682. * CheckPattern. (Only used on UNIX systems).
  683. ******************************************************************************/
  684.  
  685. #if defined(unix)
  686. static int CheckPattern (nTypes, types, strings, name)
  687. int nTypes;
  688. enum typeENUM types[];
  689. char *strings[];
  690. char *name;
  691. {
  692. int sp = 0;
  693. int i, j;
  694.  
  695. for (i = 0; i < nTypes; i++)
  696.    switch (types[i]) {
  697.      case STR:
  698.        if (strncmp(&name[sp],strings[i],strlen(strings[i])) != 0)
  699.      return FALSE;
  700.        else
  701.      sp += strlen(strings[i]);
  702.        break;
  703.      case WILD1:
  704.        if (name[sp] == NUL)
  705.      return FALSE;
  706.        else
  707.      sp++;
  708.        break;
  709.      case WILDn:
  710.        if (i == nTypes-1)    /* At last type to check? */
  711.      return TRUE;
  712.        else {
  713.      for (j = i; name[j] != NUL; j++)
  714.         if (CheckPattern (nTypes-i-1, &types[i+1],
  715.                   &strings[i+1], &name[j])) return TRUE;
  716.      return FALSE;
  717.        }
  718.    }
  719.  
  720. if (name[sp] == NUL)
  721.   return TRUE;
  722. else
  723.   return FALSE;
  724. }
  725. #endif
  726.  
  727. /******************************************************************************
  728. * DerefEnvVar. (Only used on UNIX systems).
  729. ******************************************************************************/
  730.  
  731. #if defined(unix)
  732. static void DerefEnvVar (shortP, longP)
  733. char *shortP;                /* Short path (with environment
  734.                        variables). */
  735. char *longP;                /* Long path (with environment
  736.                        variables dereferenced). */
  737. {
  738. char *Sptr = shortP;    /* Current position in "short" path. */
  739. char *Lptr = longP;    /* End position in "long" path. */
  740. char *DOLLARptr;    /* Pointer to '$' in "short" path. */
  741. char *ENVptr;        /* Pointer to environment variable in "short" path. */
  742. char *DEREFptr;        /* Pointer to dereferenced environment variable
  743.                "value". */
  744. size_t len;
  745. char *ptr;
  746. char ENVvar[MAX_ENVVAR_LEN + 1];    /* Environment variable. */
  747.  
  748. *Lptr = NUL;
  749.  
  750. for (;;) {
  751.    DOLLARptr = strchr (Sptr, '$');
  752.    if (DOLLARptr != NULL) {
  753.      len = DOLLARptr - Sptr;
  754.      if (len > 0) {
  755.        strncpy (Lptr, Sptr, len);
  756.        Lptr += len;
  757.        *Lptr = NUL;
  758.      }
  759.  
  760.      if (*(DOLLARptr + 1) == '{') {
  761.        ENVptr = DOLLARptr + 2;
  762.        ptr = strchr (ENVptr, '}');
  763.        if (ptr != NULL) {
  764.      len = ptr - ENVptr;
  765.      Sptr = ptr + 1;
  766.        }
  767.        else {
  768.      len = strlen (ENVptr);
  769.      Sptr = ENVptr + len;
  770.        }
  771.      }
  772.      else {
  773.        ENVptr = DOLLARptr + 1;
  774.        ptr = NextNonENVchar (ENVptr + 1);
  775.        if (ptr != NULL) {
  776.      len = ptr - ENVptr;
  777.      Sptr = ptr;
  778.        }
  779.        else {
  780.      len = strlen (ENVptr);
  781.      Sptr = ENVptr + len;
  782.        }
  783.      }
  784.  
  785.      strncpy (ENVvar, ENVptr, len);
  786.      ENVvar[len] = NUL;
  787.  
  788.      DEREFptr = getenv (ENVvar);
  789.  
  790.      len = strlen (DEREFptr);
  791.      if (len > 0) {
  792.        strncpy (Lptr, DEREFptr, len);
  793.        Lptr += len;
  794.        *Lptr = NUL;
  795.      }
  796.    }
  797.    else {
  798.      strcat (Lptr, Sptr);
  799.      return;
  800.    }
  801. }
  802. }
  803. #endif
  804.  
  805. /******************************************************************************
  806. * NextNonENVchar.  (Only used on UNIX systems).
  807. ******************************************************************************/
  808.  
  809. #if defined(unix)
  810. static char *NextNonENVchar (ptr)
  811. char *ptr;
  812. {
  813. while (*ptr != NUL) {
  814.   if ('\0' <= *ptr && *ptr <= '/') return ptr;
  815.   if (':' <= *ptr && *ptr <= '@') return ptr;
  816.   if ('[' <= *ptr && *ptr <= '^') return ptr;
  817.   if (*ptr == '`') return ptr;
  818.   if ('{' <= *ptr && *ptr <= '\377') return ptr;
  819.   ptr++;
  820. }
  821. return NULL;
  822. }
  823. #endif
  824.  
  825. /******************************************************************************
  826. * AppendToDir.  If necessary, appends a '/' (UNIX) or a '\' (MS DOS) to make
  827. *        a directory specification to which the file name can then be
  828. *        appended.
  829. ******************************************************************************/
  830.  
  831. void AppendToDir (dir, name)
  832. char *dir;
  833. char *name;
  834. {
  835. #if defined(vms)
  836. strcat (dir, name);
  837. #endif
  838.  
  839. #if defined(unix)
  840. if (dir[0] != NUL) {
  841.   if (dir[strlen(dir) - 1] != '/') strcat (dir, "/");
  842. }
  843. strcat (dir, name);
  844. #endif
  845.  
  846. #if defined(__MSDOS__) | defined(MSDOS)
  847. if (dir[0] != NUL) {
  848.   if (dir[strlen(dir) - 1] != '\\') strcat (dir, "\\");
  849. }
  850. strcat (dir, name);
  851. #endif
  852.  
  853. return;
  854. }
  855.  
  856. /******************************************************************************
  857. * RemoveExtensions.  Locates the last '.' in a file name and replaces it with
  858. *             a NUL.  This effectively removes the file extension.  If
  859. *             the file name does not have an extension, this could have
  860. *             undesired effects.
  861. ******************************************************************************/
  862.  
  863. void RemoveExtensions (nFiles, files)
  864. int nFiles;
  865. char *files[];
  866. {
  867. int i;
  868. char *ptr;
  869.  
  870. for (i = 0; i < nFiles; i++)
  871.    if ((ptr = strrchr(files[i],'.')) != NULL) *ptr = NUL;
  872.  
  873. return;
  874. }
  875.